package reversi;

import java.util.*;
class Board{
    public char[][] positions;
    public char turn;
    public int move_num;
    public boolean gameOver;

    public Board(){//Initialize Board.
            positions = new char[8][8];
            for(int i=0; i<64; i++){
                    positions[i/8][i%8] = 'O';
            }
            positions[3][3] = 'W';
            positions[4][4] = 'W';
            positions[3][4] = 'B';
            positions[4][3] = 'B';
            turn = 'W';
            move_num = 0;
            gameOver = false;
    
    };
	public Board(Board b){//Initialize Board.
            positions = new char[8][8];
            for(int i=0; i<64; i++){
                    positions[i/8][i%8] = b.positions[i/8][i%8];
            }
            turn = b.turn;
            move_num = b.move_num;
            gameOver = false;
    
    };
    public String printBoard(){
		String ret = "";
    	 for(int i=0; i<8; i++){
//			blaj +=(i+1) + " ";
             for (int j = 0; j < 8; j++){
            	 ret +=positions[i][j];            	 
             }
    	 }
//		 ret.add("  a b c d e f g h ");
		 return ret;
    }
//The Following functions perform check for legal moves    
public boolean checkDown(int x, int y, char player){
    	
    	if(y >= 6){
    		return false;
    	}
    	
    	if (player == 'W'){
    		if (positions[y+1][x] == 'B'){
    			for (int i = y+2; i < 8; i++){
    				if (positions[i][x] == 'O'){
    					return false;
    				}
    				else if (positions[i][x] == 'W'){
    					return true;
    				}
    			}
    		}
    		else{
    			return false;
    		}
    	}
    	else{
    		if (positions[y+1][x] == 'W'){
    			for (int i = y+2; i < 8; i++){
    				if (positions[i][x] == 'O'){
    					return false;
    				}
    				else if (positions[i][x] == 'B'){
    					return true;
    				}
    			}
    		}
    		else{
    			return false;
    		}
    	}
    	return false;
    }
    public boolean checkUp(int x, int y, char player){
    	
    	if(y <= 1){
    		return false;
    	}
    	
    	if (player == 'W'){
    		if (positions[y-1][x] == 'B'){
    			for (int i = y-2; i >= 0; i--){
    				if (positions[i][x] == 'O'){
    					return false;
    				}
    				else if (positions[i][x] == 'W'){
    					return true;
    				}
    			}
    		}
    		else{
    			return false;
    		}
    	}
    	else{
    		if (positions[y-1][x] == 'W'){
    			for (int i = y-2; i >= 0; i--){
    				if (positions[i][x] == 'O'){
    					return false;
    				}
    				else if (positions[i][x] == 'B'){
    					return true;
    				}
    			}
    		}
    		else{
    			return false;
    		}
    	}
    	return false;
    }
    public boolean checkLeft(int x, int y, char player){
    	
    	if(x <= 1){
    		return false;
    	}
    	
    	if (player == 'W'){
    		if (positions[y][x-1] == 'B'){
    			for (int i = x-2; i >= 0; i--){
    				if (positions[y][i] == 'O'){
    					return false;
    				}
    				else if (positions[y][i] == 'W'){
    					return true;
    				}
    			}
    		}
    		else{
    			return false;
    		}
    	}
    	else{
    		if (positions[y][x-1] == 'W'){
    			for (int i = x-2; i >= 0; i--){
    				if (positions[y][i] == 'O'){
    					return false;
    				}
    				else if (positions[y][i] == 'B'){
    					return true;
    				}
    			}
    		}
    		else{
    			return false;
    		}
    	}
    	return false;
    }
    public boolean checkRight(int x, int y, char player){
    	
    	if(x >= 6){
    		return false;
    	}
    	
    	if (player == 'W'){
    		if (positions[y][x+1] == 'B'){
    			for (int i = x+2; i < 8; i++){
    				if (positions[y][i] == 'O'){
    					return false;
    				}
    				else if (positions[y][i] == 'W'){
    					return true;
    				}
    			}
    		}
    		else{
    			return false;
    		}
    	}
    	else{
    		if (positions[y][x+1] == 'W'){
    			for (int i = x+2; i < 8; i++){
    				if (positions[y][i] == 'O'){
    					return false;
    				}
    				else if (positions[y][i] == 'B'){
    					return true;
    				}
    			}
    		}
    		else{
    			return false;
    		}
    	}
    	return false;
    }
    
    public boolean checkNorthWest(int x, int y, char player){
    	if ( x < 2 || y < 2){
			return false;
		}
    	if (player == 'W'){
    		if (positions[y-1][x-1] == 'B'){
    				
    			int j = y-2;
    			for (int i = x-2; (i >= 0 && j >= 0); i--){
    					
    				if (positions[j][i] == 'O'){
        				return false;
        			}
        			else if (positions[j][i] == 'W'){
        				return true;
        			}
    				j--;
    			}
    		}
    	}
    	
    	else{
    		if (positions[y-1][x-1] == 'W'){
				
    			int j = y-2;
    			for (int i = x-2; (i >= 0 && j >= 0); i--){
    					
    				if (positions[j][i] == 'O'){
        				return false;
        			}
        			else if (positions[j][i] == 'B'){
        				return true;
        			}
    				j--;
    			}
    		}
    	}
    	return false;
    }
    public boolean checkNorthEast(int x, int y, char player){
    	if ( x >= 6 || y < 2){
			return false;
		}
    	if (player == 'W'){
    		if (positions[y-1][x+1] == 'B'){
    				
    			int j = y-2;
    			for (int i = x+2; (i <8 && j >= 0); i++){
    					
    				if (positions[j][i] == 'O'){
        				return false;
        			}
        			else if (positions[j][i] == 'W'){
        				return true;
        			}
    				j--;
    			}
    		}
    	}
    	
    	else{
    		if (positions[y-1][x+1] == 'W'){
				
    			int j = y-2;
    			for (int i = x+2; (i <8 && j >= 0); i++){
    					
    				if (positions[j][i] == 'O'){
        				return false;
        			}
        			else if (positions[j][i] == 'B'){
        				return true;
        			}
    				j--;
    			}
    		}
    	}
    	return false;
    }
    public boolean checkSouthWest(int x, int y, char player){
    	if ( x < 2 || y >= 6){
			return false;
		}
    	if (player == 'W'){
    		if (positions[y+1][x-1] == 'B'){
    				
    			int j = y+2;
    			for (int i = x-2; (i >= 0 && j < 8); i--){
    					
    				if (positions[j][i] == 'O'){
        				return false;
        			}
        			else if (positions[j][i] == 'W'){
        				return true;
        			}
    				j++;
    			}
    		}
    	}
    	
    	else{
    		if (positions[y+1][x-1] == 'W'){
				
    			int j = y+2;
    			for (int i = x-2; (i >= 0 && j < 8); i--){
    					
    				if (positions[j][i] == 'O'){
        				return false;
        			}
        			else if (positions[j][i] == 'B'){
        				return true;
        			}
    				j++;
    			}
    		}
    	}
    	
    	
    	
    	return false;
    }
    public boolean checkSouthEast(int x, int y, char player){
    	if ( x >= 6 || y >= 6){
			return false;
		}
    	if (player == 'W'){
    		if (positions[y+1][x+1] == 'B'){
    				
    			int j = y+2;
    			for (int i = x+2; (i < 8 && j < 8); i++){
    					
    				if (positions[j][i] == 'O'){
        				return false;
        			}
        			else if (positions[j][i] == 'W'){
        				return true;
        			}
    				j++;
    			}
    		}
    	}
    	
    	else{
    		if (positions[y+1][x+1] == 'W'){
				
    			int j = y+2;
    			for (int i = x+2; (i < 8 && j < 8); i++){
    					
    				if (positions[j][i] == 'O'){
        				return false;
        			}
        			else if (positions[j][i] == 'B'){
        				return true;
        			}
    				j++;
    			}
    		}
    	}
    	return false;
    	
    }
   //These 8 functions flip pieces
    private void performDown(int x, int y, char player){

    	if (player == 'W'){
    		if (positions[y+1][x] == 'B'){
    			positions[y+1][x] = 'W';
    			for (int i = y+2; i < 8; i++){
    				if (positions[i][x] == 'B'){
    					positions[i][x] = 'W';
    				}
    				else if (positions[i][x] == 'W'){
    					break;
    				}
    			}
    		}
    	}
    	else{
    		if (positions[y+1][x] == 'W'){
    			positions[y+1][x] = 'B';
    			for (int i = y+2; i < 8; i++){
    				if (positions[i][x] == 'W'){
    					positions[i][x] = 'B';
    				}
    				else if (positions[i][x] == 'B'){
    					break;
    				}
    			}
    		}
    	}
    }
    private void performUp(int x, int y, char player){
    	if (player == 'W'){
    		if (positions[y-1][x] == 'B'){
    			positions[y-1][x] = 'W';
    			for (int i = y-2; i >= 0 ; i--){
    				if (positions[i][x] == 'B'){
    					positions[i][x] = 'W';
    				}else if (positions[i][x] == 'W'){
    					break;
    				}
    			}
    		}
    	}
    	else{
    		if (positions[y-1][x] == 'W'){
    			positions[y-1][x] = 'B';
    			for (int i = y-2; i >= 0; i--){
    				if (positions[i][x] == 'W'){
    					positions[i][x] = 'B';
    				}else if (positions[i][x] == 'B'){
    					break;
    				}
    			}
    		}
    	}
    }
    private void performLeft(int x, int y, char player){
    	if (player == 'W'){
    		if (positions[y][x-1] == 'B'){
    			positions[y][x-1] = 'W';
    			for (int i = x-2; i >= 0 ; i--){
    				if (positions[y][i] == 'B'){
    					positions[y][i] = 'W';
    				}else if (positions[y][i] == 'W'){
    					break;
    				}
    			}
    		}
    	}
    	else{
    		if (positions[y][x-1] == 'W'){
    			positions[y][x-1] = 'B';
    			for (int i = x-2; i >= 0; i--){
    				if (positions[y][i] == 'W'){
    					positions[y][i] = 'B';
    				}else if (positions[y][i] == 'B'){
    					break;
    				}
    			}
    		}
    	}
    }
    private void performRight(int x, int y, char player){
    	if (player == 'W'){
    		if (positions[y][x+1] == 'B'){
    			positions[y][x+1] = 'W';
    			for (int i = x+2; i < 8 ; i++){
    				if (positions[y][i] == 'B'){
    					positions[y][i] = 'W';
    				}else if (positions[y][i] == 'W'){
    					break;
    				}
    			}
    		}
    	}
    	else{
    		if (positions[y][x+1] == 'W'){
    			positions[y][x+1] = 'B';
    			for (int i = x+2; i <8; i++){
    				if (positions[y][i] == 'W'){
    					positions[y][i] = 'B';
    				}else if (positions[y][i] == 'B'){
    					break;
    				}
    			}
    		}
    	}
    }
    private void performNorthWest(int x, int y, char player){
    	if (player == 'W'){
    		if (positions[y-1][x-1] == 'B'){
    			positions[y-1][x-1] = 'W';
    			int j = y-2;
    			for (int i = x-2; (i >= 0 && j >= 0) ; i--){
    				if (positions[j][i] == 'B'){
    					positions[j][i] = 'W';
    				}else if (positions[j][i] == 'W'){
    					break;
    				}
    				j--;
    			}
    		}
    	}
    	else{
    		if (positions[y-1][x-1] == 'W'){
    			positions[y-1][x-1] = 'B';
    			int j = y-2;
    			for (int i = x-2; (i >= 0 && j >= 0) ; i--){
    				if (positions[j][i] == 'W'){
    					positions[j][i] = 'B';
    				}else if (positions[j][i] == 'B'){
    					break;
    				}
    				j--;
    			}
    		}
    	}
    }
    private void performNorthEast(int x, int y, char player){
    	if (player == 'W'){
    		if (positions[y-1][x+1] == 'B'){
    			positions[y-1][x+1] = 'W';
    			int j = y-2;
    			for (int i = x+2; (i < 8 && j >= 0) ; i++){
    				if (positions[j][i] == 'B'){
    					positions[j][i] = 'W';
    				}else if (positions[j][i] == 'W'){
    					break;
    				}
    				j--;
    			}
    		}
    	}
    	else{
    		if (positions[y-1][x+1] == 'W'){
    			positions[y-1][x+1] = 'B';
    			int j = y-2;
    			for (int i = x+2; (i < 8 && j >= 0) ; i++){
    				if (positions[j][i] == 'W'){
    					positions[j][i] = 'B';
    				}else if (positions[j][i] == 'B'){
    					break;
    				}
    				j--;
    			}
    		}
    	}
    }
    private void performSouthWest(int x, int y, char player){
    	if (player == 'W'){
    		if (positions[y+1][x-1] == 'B'){
    			positions[y+1][x-1] = 'W';
    			int j = y+2;
    			for (int i = x-2; (i >= 0 && j < 8) ; i--){
    				if (positions[j][i] == 'B'){
    					positions[j][i] = 'W';
    				}else if (positions[j][i] == 'W'){
    					break;
    				}
    				j++;
    			}
    		}
    	}
    	else{
    		if (positions[y+1][x-1] == 'W'){
    			positions[y+1][x-1] = 'B';
    			int j = y+2;
    			for (int i = x-2; (i >= 0 && j < 8) ; i--){
    				if (positions[j][i] == 'W'){
    					positions[j][i] = 'B';
    				}else if (positions[j][i] == 'B'){
    					break;
    				}
    				j++;
    			}
    		}
    	}
    }
    private void performSouthEast(int x, int y, char player){
    	if (player == 'W'){
    		if (positions[y+1][x+1] == 'B'){
    			positions[y+1][x+1] = 'W';
    			int j = y+2;
    			for (int i = x+2; (i < 8 && j < 8) ; i++){
    				if (positions[j][i] == 'B'){
    					positions[j][i] = 'W';
    				}else if (positions[j][i] == 'W'){
    					break;
    				}
    				j++;
    			}
    		}
    	}
    	else{
    		if (positions[y+1][x+1] == 'W'){
    			positions[y+1][x+1] = 'B';
    			int j = y+2;
    			for (int i = x+2; (i < 8 && j < 8) ; i++){
    				if (positions[j][i] == 'W'){
    					positions[j][i] = 'B';
    				}else if (positions[j][i] == 'B'){
    					break;
    				}
    				j++;
    			}
    		}
    	}
    }

    public boolean isLegal(int x, int y, char player){
    
    	boolean valid = false;
    	//Check to see if x and y are in bounds
    	if (x < 0 || x > 7 || y <0 || y > 7){
    		return false;
    	}
		if(positions[y][x]!='O'){ return false;}
    	//check to see if there are legal vertical moves
    	valid = valid || checkDown(x, y, player) || checkUp(x, y, player);
    	//check for legal horizontal moves
    	valid = valid || checkRight(x, y, player) || checkLeft(x, y, player);
    	//Diagonal
    	valid = valid || checkSouthEast(x, y, player) || checkNorthEast(x, y, player) 
    			|| checkSouthWest(x, y, player) || checkNorthWest(x, y, player);    	
    	
    	return valid;
    }
    public boolean isGameOver(){
    	if (listLegalMoves('B').size() < 1 && listLegalMoves('W').size() < 1){
    		return true;
    	}
    	else{
    		return false;
    	}
    }
    //Right now I just brute force this
    public ArrayList<int[]> listLegalMoves(char player){
    	ArrayList<int[]> legalMoves = new ArrayList();
    	for (int i = 0; i < 8; i++){
    		for (int j = 0; j < 8; j++){
    			if (isLegal(i, j, player)){
    				int[] b = new int[2];
    				b[0] = i;
    				b[1] = j;
    				legalMoves.add(b);
    			}
    		}
    	}
    	return legalMoves;
    }
    //A testing function so I can manually adjust the board if needed
    public void setPosition(int x, int y, char player){
    	positions[y][x] = player;
    	
    	
    }
    //Performs legal moves- returns true if successful
    public boolean performMove(int x, int y, char player){
    	//First check to see if the move is legal
    	if (isLegal(x, y, player)){
    		
    		//For each of the "check" functions, if they're true then
    		//we go through "perform" functions which flip pieces
    		if (checkUp(x, y, player)){
//    			System.out.println("up");
    			performUp(x, y, player);
    		}
    		if (checkDown(x, y, player)){
//    			System.out.println("down");
    			performDown(x,y, player);
    		}
    		if (checkLeft(x, y, player)){
//    			System.out.println("left");
    			performLeft(x, y, player);
    		}
    		if (checkRight(x,y, player)){
//    			System.out.println("right");
    			performRight(x, y, player);
    		}
    		if (checkNorthWest(x, y, player)){
//    			System.out.println("nw");
    			performNorthWest(x, y, player);
    		}
    		if (checkNorthEast(x, y, player)){
//    			System.out.println("ne");
    			performNorthEast(x, y, player);
    		}
    		if (checkSouthWest(x, y, player)){
//    			System.out.println("sw");
    			performSouthWest(x, y, player);
    		}
    		if (checkSouthEast(x, y, player)){
//    			System.out.println("se");
    			performSouthEast(x, y, player);
    		}
    		positions[y][x] = player;
    		if (player == 'W'){
    			turn = 'B';
    		}
    		else{
    			turn = 'W';
    		}
    		return true;
    	}else{
    		return false;
    	}
    	
    	
    }
    public char getTurn(){
    	return turn;
    }
    public int countWhite(){
    	int w = 0;
    	for(int i=0; i<8; i++){
            for (int j = 0; j < 8; j++){
            	if (positions[i][j] == 'W'){
            		w++;
            	}
            }
    	}
    	return w;
    }
    public int countBlack(){
    	int b = 0;
    	for(int i=0; i<8; i++){
            for (int j = 0; j < 8; j++){
            	if (positions[i][j] == 'B'){
            		b++;
            	}
            }
    	}
    	return b;
    }
	public int Heuristic(char c){//Assumed that this is the maximizing player.
		int pieceDiff = 0;
		int enemyPieces = 0;
		int enemyMoves = 0;
		int sideDiff = 0;
		if(c == 'B'){
			pieceDiff = countBlack() - countWhite();
			enemyMoves = listLegalMoves('W').size();
		}else{
			pieceDiff = countWhite()- countBlack();
			enemyMoves = listLegalMoves('B').size();
		}
		for(int i=0; i<8; i++){//Counts Sides.  Corners count for more.
			if(positions[i][0]==c) sideDiff++;
			else if(positions[i][0]!='O') sideDiff--;
			if(positions[i][7]==c) sideDiff++;
			else if(positions[i][7]!='O') sideDiff--;
			if(positions[0][i]==c) sideDiff++;
			else if(positions[0][i]!='O') sideDiff--;
			if(positions[7][i]==c) sideDiff++;
			else if(positions[7][i]!='O') sideDiff--;
			if((i==0 || i==7) && (positions[i][0]==c || positions[i][7]==c)) sideDiff+=7;
			if((i==0 || i==7) && ((positions[i][0]!='O'&& positions[i][0]!=c)|| (positions[i][7]!='O'&&positions[i][0]!=c))) sideDiff-=7;
		}
		return pieceDiff + 2*sideDiff  - 8*enemyMoves;		
	}
    public char whoWon(){
    	if (isGameOver() == false){
    		return 'N';
    	}
    	else{
    		int w = countWhite();
    		int b = countBlack();
    		if (w == b){
    			return 'N';
    		}
    		else if (w > b){
    			return 'W';
    		}
    		else{
    			return 'B';
    		}
    	}
    }
    
   
}